package com.ai.learning.framework.common.util;

import org.springframework.stereotype.Component;

import java.net.InetAddress;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;

/**
 * ID生成器工具类
 * 支持雪花算法、UUID等多种ID生成方式
 * 与Python Django后端的ID生成策略保持一致
 */
@Component
public class IdGenerator {

    /**
     * 雪花算法ID生成器
     */
    private final SnowflakeIdWorker snowflakeIdWorker;

    public IdGenerator() {
        // 根据机器IP生成workerId和datacenterId
        long workerId = getWorkerId();
        long datacenterId = getDatacenterId();
        this.snowflakeIdWorker = new SnowflakeIdWorker(workerId, datacenterId);
    }

    /**
     * 生成雪花算法ID
     */
    public long snowflakeId() {
        return snowflakeIdWorker.nextId();
    }

    /**
     * 生成带业务前缀的雪花ID
     */
    public String businessId(String prefix) {
        return prefix + snowflakeId();
    }

    /**
     * 生成UUID（去掉横线）
     */
    public String uuid() {
        return UUID.randomUUID().toString().replace("-", "");
    }

    /**
     * 生成UUID（保留横线）
     */
    public String uuidWithDash() {
        return UUID.randomUUID().toString();
    }

    /**
     * 生成带前缀的UUID
     */
    public String uuidWithPrefix(String prefix) {
        return prefix + uuid();
    }

    /**
     * 生成用户ID（与Django User模型兼容）
     */
    public String userId() {
        return businessId("USER_");
    }

    /**
     * 生成智能体ID
     */
    public String agentId() {
        return businessId("AGENT_");
    }

    /**
     * 生成对话ID
     */
    public String conversationId() {
        return businessId("CONV_");
    }

    /**
     * 生成消息ID
     */
    public String messageId() {
        return businessId("MSG_");
    }

    /**
     * 生成知识库ID
     */
    public String knowledgeBaseId() {
        return businessId("KB_");
    }

    /**
     * 生成文档ID
     */
    public String documentId() {
        return businessId("DOC_");
    }

    /**
     * 生成订单号
     */
    public String orderNo() {
        return businessId("ORDER_");
    }

    /**
     * 获取workerId（基于IP地址）
     */
    private long getWorkerId() {
        try {
            InetAddress address = InetAddress.getLocalHost();
            byte[] ipAddressBytes = address.getAddress();
            return ((ipAddressBytes[ipAddressBytes.length - 1] & 0xFF) +
                    (ipAddressBytes[ipAddressBytes.length - 2] & 0xFF) * 256) % 32;
        } catch (Exception e) {
            return ThreadLocalRandom.current().nextLong(0, 32);
        }
    }

    /**
     * 获取datacenterId（基于IP地址）
     */
    private long getDatacenterId() {
        try {
            InetAddress address = InetAddress.getLocalHost();
            byte[] ipAddressBytes = address.getAddress();
            return ((ipAddressBytes[ipAddressBytes.length - 3] & 0xFF) +
                    (ipAddressBytes[ipAddressBytes.length - 4] & 0xFF) * 256) % 32;
        } catch (Exception e) {
            return ThreadLocalRandom.current().nextLong(0, 32);
        }
    }

    /**
     * 雪花算法实现类
     */
    private static class SnowflakeIdWorker {
        
        /** 开始时间戳 (2023-01-01) */
        private final long twepoch = 1672531200000L;

        /** 机器id所占的位数 */
        private final long workerIdBits = 5L;

        /** 数据标识id所占的位数 */
        private final long datacenterIdBits = 5L;

        /** 支持的最大机器id，结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) */
        private final long maxWorkerId = -1L ^ (-1L << workerIdBits);

        /** 支持的最大数据标识id，结果是31 */
        private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);

        /** 序列在id中占的位数 */
        private final long sequenceBits = 12L;

        /** 机器ID向左移12位 */
        private final long workerIdShift = sequenceBits;

        /** 数据标识id向左移17位(12+5) */
        private final long datacenterIdShift = sequenceBits + workerIdBits;

        /** 时间戳向左移22位(5+5+12) */
        private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;

        /** 生成序列的掩码，这里为4095 (0b111111111111=0xfff=4095) */
        private final long sequenceMask = -1L ^ (-1L << sequenceBits);

        /** 工作机器ID(0~31) */
        private long workerId;

        /** 数据中心ID(0~31) */
        private long datacenterId;

        /** 毫秒内序列(0~4095) */
        private long sequence = 0L;

        /** 上次生成ID的时间戳 */
        private long lastTimestamp = -1L;

        /**
         * 构造函数
         * @param workerId 工作ID (0~31)
         * @param datacenterId 数据中心ID (0~31)
         */
        public SnowflakeIdWorker(long workerId, long datacenterId) {
            if (workerId > maxWorkerId || workerId < 0) {
                throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
            }
            if (datacenterId > maxDatacenterId || datacenterId < 0) {
                throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
            }
            this.workerId = workerId;
            this.datacenterId = datacenterId;
        }

        /**
         * 获得下一个ID (该方法是线程安全的)
         * @return SnowflakeId
         */
        public synchronized long nextId() {
            long timestamp = timeGen();

            // 如果当前时间小于上一次ID生成的时间戳，说明系统时钟回退过这个时候应当抛出异常
            if (timestamp < lastTimestamp) {
                throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
            }

            // 如果是同一时间生成的，则进行毫秒内序列
            if (lastTimestamp == timestamp) {
                sequence = (sequence + 1) & sequenceMask;
                // 毫秒内序列溢出
                if (sequence == 0) {
                    // 阻塞到下一个毫秒,获得新的时间戳
                    timestamp = tilNextMillis(lastTimestamp);
                }
            }
            // 时间戳改变，毫秒内序列重置
            else {
                sequence = 0L;
            }

            // 上次生成ID的时间戳
            lastTimestamp = timestamp;

            // 移位并通过或运算拼到一起组成64位的ID
            return ((timestamp - twepoch) << timestampLeftShift) //
                    | (datacenterId << datacenterIdShift) //
                    | (workerId << workerIdShift) //
                    | sequence;
        }

        /**
         * 阻塞到下一个毫秒，直到获得新的时间戳
         * @param lastTimestamp 上次生成ID的时间戳
         * @return 当前时间戳
         */
        protected long tilNextMillis(long lastTimestamp) {
            long timestamp = timeGen();
            while (timestamp <= lastTimestamp) {
                timestamp = timeGen();
            }
            return timestamp;
        }

        /**
         * 返回以毫秒为单位的当前时间
         * @return 当前时间(毫秒)
         */
        protected long timeGen() {
            return System.currentTimeMillis();
        }
    }
}